import React, {
  ReactElement,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState
} from 'react';
import { View, Text, Image } from 'react-native';

import styles from './style';
import { Store } from '../../reducer';
import Button from '../../../../components/Button';
import { hideInstantAnswer, uploadUserInstantAnswer } from '../../actions';
import { IMPROMPTU_SHADOW_OPTIONS } from '../../../../constant/shadow';
import { instantTime } from '../../../../constant/resource';
import { getUserInfo } from '../../../../store/user';
import { UserRole } from '../../constant';

let timer: NodeJS.Timer | null;
let showResTimer: NodeJS.Timer | null;
let localNeedShowRes: boolean;
let haveSelectedAnswer: boolean;

const clearTimer = (): void => {
  if (timer) {
    clearInterval(timer);
    timer = null;
  }
  if (showResTimer) {
    clearTimeout(showResTimer);
    showResTimer = null;
  }
};

export default (): ReactElement => {
  const { state } = useContext(Store);
  const { instantAnswerInfo } = state;
  const { show, instantAnswer } = instantAnswerInfo;
  const { options, duration, title, instantAnswerId } = instantAnswer;
  const { textStr: problem } = title || { textStr: '', textType: 0 };

  const leftAnswer = options.length > 0 && options[0];
  const rightAnswer = options.length > 1 && options[1];

  const [showRes, setShowRes] = useState(false);
  const [isCorrect, setIsCorrect] = useState(false);
  const [selectedAnswer, setSelectedAnswer] = useState('');
  const [time, setTime] = useState<number>(0);
  const [width, setWidth] = useState<number>(0);
  const [height, setHeight] = useState<number>(0);

  const { role } = getUserInfo();
  const isParent = role === UserRole.Parent;

  const onSelectedAnswer = useCallback(
    async (a: string): Promise<void> => {
      if (haveSelectedAnswer) return;
      haveSelectedAnswer = true;

      setSelectedAnswer(a);
      localNeedShowRes = true;
      const { needShowRes, isCorrect: correct } = await uploadUserInstantAnswer(
        a,
        time
      );
      if (!needShowRes) return;

      clearTimer();
      setIsCorrect(!!correct);
      setTimeout((): void => {
        if (!localNeedShowRes) return;
        setShowRes(true);
        showResTimer = setTimeout((): void => {
          hideInstantAnswer();
        }, 2000);
      }, 500);
    },
    [time]
  );

  useEffect((): (() => void) => {
    clearTimer();
    if (show) {
      setTime(duration / 1000);
      timer = setInterval((): void => {
        let canHideInstant = false;
        setTime((t): number => {
          const resTime = t - 1;
          if (resTime < 0) {
            canHideInstant = true;
            clearTimer();
            return t;
          }
          return resTime;
        });
        if (canHideInstant) {
          hideInstantAnswer();
          uploadUserInstantAnswer('', 0);
        }
      }, 1000);
    } else {
      localNeedShowRes = false;
      haveSelectedAnswer = false;
      setWidth(0);
      setHeight(0);
      setShowRes(false);
      setIsCorrect(false);
      setSelectedAnswer('');
    }
    return (): void => {
      localNeedShowRes = false;
      haveSelectedAnswer = false;
      clearTimer();
      setShowRes(false);
      setIsCorrect(false);
      setSelectedAnswer('');
    };
  }, [duration, show, instantAnswerId]);

  const getResStyleWithAnswer = useCallback(
    (a: string): any => {
      let resStyle;
      if (!showRes) return resStyle;

      if (isCorrect) {
        if (selectedAnswer === a) {
          resStyle = styles.correctAnswer;
        }
        return resStyle;
      }

      if (selectedAnswer === a) {
        resStyle = styles.wrongAnswer;
      } else {
        resStyle = styles.correctAnswer;
      }
      return resStyle;
    },
    [isCorrect, selectedAnswer, showRes]
  );

  return useMemo((): ReactElement => {
    if (!show) return <View />;
    const haveProblem = problem && problem.length > 0;
    const leftResStyle = getResStyleWithAnswer(leftAnswer || '');
    const rightResStyle = getResStyleWithAnswer(rightAnswer || '');
    return (
      <View style={styles.container}>
        <View style={styles.shadowContainer}>
          {width > 0 && height > 0 && (
            <Button
              needSVGShadow
              shadowStyle={[styles.shadow, { width, height }]}
              shadowOptions={IMPROMPTU_SHADOW_OPTIONS}
              style={[styles.content, { width, height }]}
              activity={false}
            />
          )}
          <View
            style={[
              styles.shadowContent,
              haveProblem ? styles.haveProblem : {}
            ]}
            onLayout={(e): void => {
              const { width: w, height: h } = e.nativeEvent.layout;
              setWidth(w);
              setHeight(h);
            }}
          >
            <View style={styles.leftContent}>
              <View style={styles.timeContent}>
                <Image
                  style={styles.timeIcon}
                  source={instantTime}
                  resizeMode="contain"
                />
                <Text style={styles.timeDesc}>{time}</Text>
              </View>
              <Text style={styles.problem}>{problem}</Text>
            </View>
            <View style={styles.rightContent}>
              {leftAnswer && (
                <Button
                  style={[
                    styles.answer,
                    haveProblem ? styles.haveProblemAnswer : {},
                    leftResStyle
                  ]}
                  onPress={(): void => {
                    onSelectedAnswer(leftAnswer);
                  }}
                  hitSlop={{ left: 20, top: 20, right: 0, bottom: 20 }}
                  activity={!isParent}
                >
                  <Text
                    style={[
                      styles.answerDesc,
                      leftResStyle ? {} : styles.blackDesc
                    ]}
                  >
                    {leftAnswer}
                  </Text>
                  {selectedAnswer === leftAnswer && !showRes ? (
                    <View style={styles.selectedAnswer} />
                  ) : null}
                </Button>
              )}
              {rightAnswer && (
                <Button
                  style={[
                    styles.answer,
                    styles.rightAnswer,
                    haveProblem ? styles.haveProblemAnswer : {},
                    rightResStyle
                  ]}
                  onPress={(): void => {
                    onSelectedAnswer(rightAnswer);
                  }}
                  hitSlop={{ left: 0, top: 20, right: 20, bottom: 20 }}
                  activity={!isParent}
                >
                  <Text
                    style={[
                      styles.answerDesc,
                      rightResStyle ? {} : styles.blackDesc
                    ]}
                  >
                    {rightAnswer}
                  </Text>
                  {selectedAnswer === rightAnswer && !showRes ? (
                    <View style={styles.selectedAnswer} />
                  ) : null}
                </Button>
              )}
            </View>
          </View>
        </View>
      </View>
    );
  }, [
    getResStyleWithAnswer,
    height,
    isParent,
    leftAnswer,
    onSelectedAnswer,
    problem,
    rightAnswer,
    selectedAnswer,
    show,
    showRes,
    time,
    width
  ]);
};
